/*
 * @Author: secrets123
 * @Date: 2022-07-21 10:53:28
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2023-09-22 13:42:54
 * @FilePath: \stm32g431_AllRings\applications\fdcan_app.c
 * @Description:
 *
 * Copyright (c) 2022 by secrets123 1097290967@qq.com, All Rights Reserved.
 */
#include <rtthread.h>
#include <rtconfig.h>
#include <board.h>
#include "fdcan_app.h"
#include "rs485.h"
#include <string.h>
#include "allrings_sys.h"
#include "iap_para.h"
#ifdef TEST_VALUE
// fdcan-process
uint8_t fdcan_testdata[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
#endif
/****************************THREAD-FDCAN*******************/

/*thread*/
#define THREAD_STACK_FDCAN1_RX 1024
#define THREAD_PRIO_FDCAN1_RX 6

#define THREAD_STACK_FDCAN_ANALYSIS 1024
#define THREAD_PRIO_FDCAN_ANALYSIS 24

/*messegequeue*/
static rt_mq_t fdcan1_msg = RT_NULL;

// struct rt_messagequeue fdcan1_msg;
#ifdef FDCAN_USE_RINGBUFF
/*mutex*/
static rt_mutex_t rb_fdcan_mutex = RT_NULL;
/*ringbuffer*/
struct rt_ringbuffer ringbuffer_fdcan_rollup; // 创建环形缓冲，用于存储FDCAN接收数据
rt_uint8_t rbpool_fdcan_rollup[5 * 1024];     // 创建环形缓冲池

#endif

/*-------------------------------------------------------------------*/
void tfdcan1_rx_entry(void *parameters)
{
    rt_err_t sta = RT_EOK;
    uint8_t cmd;
    struct _fdcan_rxdata fdcan1_rxmsg;
    // static uint32_t fram = 0;
    while (1)
    {
        sta = rt_mq_recv(fdcan1_msg, &fdcan1_rxmsg, sizeof(fdcan1_rxmsg), RT_WAITING_FOREVER);
        if (sta != RT_EOK)
        {
            rt_kprintf("fdcan1_mq got a innormal sta: %d! \r\n", sta);
        }
        else
        {
            cmd = fdcan1_rxmsg.data[0];
            switch (cmd) // 请求对应的设备
            {
            case ALLRINGS_SYS_READ_HANDSHAKE:
                allrings_sys_r_handshake(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_SWVERSION:
                allrings_sys_r_swversion(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_ADDRS:
                allrings_sys_r_addrs(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_MODE:
                allrings_sys_w_mode(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_MODE:
                allrings_sys_r_mode(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_SAVEPARA:
                allrings_sys_w_savedpara(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_SWITCH:
                allrings_sys_w_switch(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_SWITCH:
                allrings_sys_r_switch(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_RES485:
                allrings_sys_w_res_rs485(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_CANID:
                allrings_sys_w_canid(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_FDCANINDEX:
                allrings_sys_w_fdcanindex(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_FDCANINDEX:
                allrings_sys_r_fdcanindex(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_HWVERSION:
                allrings_sys_r_hwversion(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_IAP_FLAG:
                allrings_sys_w_iap(&rings_ctr, &fdcan1_rxmsg);
                break;
            case AIIRINGS_SYS_READ_DEVICE:
                allrings_sys_r_device(&rings_ctr, &fdcan1_rxmsg);
                break;
            case AIIRINGS_SYS_SET_DEVICE:
                allrings_sys_w_device(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_CLEAR:
                allrings_sys_w_clear(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_ERR:
                allrings_sys_r_err(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_CAN_RES:
                allrings_sys_w_canres(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_CAN_RES:
                allrings_sys_r_canres(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_SET_485_RES:
                allrings_sys_w_485res(&rings_ctr, &fdcan1_rxmsg);
                break;
            case ALLRINGS_SYS_READ_485_RES:
                allrings_sys_r_485res(&rings_ctr, &fdcan1_rxmsg);
                break;

            default: // 除系统指令之外的挂载设备指令
                     // allrings_device_ctr(&rings_ctr, &allrings_paras, &fdcan1_rxmsg);

#ifdef FDCAN_USE_RINGBUFF
                     // 将数据装载到环形缓冲区中
                rt_mutex_take(rb_fdcan_mutex, RT_WAITING_FOREVER);

                if (rt_ringbuffer_status(&ringbuffer_fdcan_rollup) != RT_RINGBUFFER_FULL)                                 // 环形缓冲不满
                    rt_ringbuffer_put(&ringbuffer_fdcan_rollup, (const rt_uint8_t *)&fdcan1_rxmsg, sizeof(fdcan1_rxmsg)); //(fdcan1_rxmsg.dta_length+4));      //fdcan1-id / length / datas

                rt_mutex_release(rb_fdcan_mutex);
#else
                allrings_device_ctr(&rings_ctr, &allrings_paras, &fdcan1_rxmsg);
#endif
                break;
            }
        }
    }
}

void tfdcan_analysis_entry(void *parameters)
{
    struct _fdcan_rxdata ays_fdcan_dta;
    extern rt_device_t serial_bridge;
    rt_size_t data_length = 0;

    while (1)
    {
        // allrings_sys_init(&rings_ctr);
        rt_mutex_take(rb_fdcan_mutex, RT_WAITING_FOREVER); // 等待2ms
        data_length = rt_ringbuffer_get(&ringbuffer_fdcan_rollup, (rt_uint8_t *)&ays_fdcan_dta, sizeof(struct _fdcan_rxdata));

        if (data_length <= 0)
        {
            rings_ctr.allrings_values.analaysis_data_type = RB_DATA_IDLE; // 无控制数据
            // upper_candata2modbus_analysis(&rings_ctr, &ays_fdcan_dta); // 从缓冲区中，解析上层的命令
        }
        else
            rings_ctr.allrings_values.analaysis_data_type = RB_DATA_BUSY; // 有控制数据
        rt_mutex_release(rb_fdcan_mutex);                                 // 解锁

        allrings_device_ctr(&rings_ctr, &allrings_paras, &ays_fdcan_dta);

        rt_thread_mdelay(1); // 固定2ms解析FDCAN反馈数据
    }
}

int fdcan_app(void)
{
    rt_err_t rt_sta = RT_EOK;

    rt_thread_t tfdcan1_receive = RT_NULL;
    rt_thread_t tfdcan_analysis = RT_NULL;

    // 设置匹配电阻
    rt_pin_mode(CAN_REN_PIN, PIN_MODE_OUTPUT);
    CAN_REN_EN(); // 默认开启匹配电阻

    /*init mutex*/
    rb_fdcan_mutex = rt_mutex_create("rb_fdcan", RT_IPC_FLAG_FIFO);
    if (rb_fdcan_mutex == RT_NULL)
        return rt_sta = RT_ERROR;

    /*init msg-queue*/
    fdcan1_msg = rt_mq_create("fdcan1_mq", sizeof(struct _fdcan_rxdata), 50, RT_IPC_FLAG_FIFO);

    if (fdcan1_msg == RT_NULL)
        return rt_sta = RT_ERROR;

    /*init thread*/
    tfdcan1_receive = rt_thread_create("can1_rx", tfdcan1_rx_entry, RT_NULL,
                                       THREAD_STACK_FDCAN1_RX, THREAD_PRIO_FDCAN1_RX, 50);

    tfdcan_analysis = rt_thread_create("can_ays", tfdcan_analysis_entry, RT_NULL,
                                       THREAD_STACK_FDCAN_ANALYSIS, THREAD_PRIO_FDCAN_ANALYSIS, 50);

    if (tfdcan1_receive != RT_NULL)
    {
        rt_ringbuffer_init(&ringbuffer_fdcan_rollup, rbpool_fdcan_rollup, sizeof(rbpool_fdcan_rollup)); // 创建can_接收环形缓冲
        rt_thread_startup(tfdcan1_receive);                                                             // 启动两个can-rx线程
    }
    else
    {
        rt_kprintf("fdcan_rx thread create failed! \r\n");
        return rt_sta = RT_ERROR;
    }

    if (tfdcan_analysis != RT_NULL)
    {
        rt_thread_startup(tfdcan_analysis);
    }
    else
    {
        rt_kprintf("fdcan_tx thread create failed! \r\n");
        return rt_sta = RT_ERROR;
    }
    return rt_sta;
}
INIT_APP_EXPORT(fdcan_app);

void rt_fdcan1_irq_feedback(void *user, uint8_t *pdata)
{
    static uint32_t fdcan1_rxirq_num;
    static struct _fdcan_rxdata fdcan1_rx = {0};
    static FDCAN_RxHeaderTypeDef *rx_header1;

    rx_header1 = (FDCAN_RxHeaderTypeDef *)user;

    fdcan1_rx.dta_length = (rx_header1->DataLength) >> 16;
    fdcan1_rx.id = (uint8_t)(rx_header1->Identifier);
    memcpy(&fdcan1_rx.data, pdata, fdcan1_rx.dta_length);

    rt_mq_send(fdcan1_msg, &fdcan1_rx, sizeof(struct _fdcan_rxdata));

    fdcan1_rxirq_num++;
    // LOG_I("fdcan rx %d messenge:%x !\r\n", fdcan1_rx.dta_length, fdcan1_rx.data);
}

/**********************************************************************************************/
